﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Project.Database.Repository
{
    public partial class DatabaseRepository
    {
        #region Properties
        #endregion

        #region Query Methods

        public Blog GetBlog(string URL)
        {
            return entities.Blogs.SingleOrDefault(blog => blog.URL == URL);
        }

        public Blog GetBlog(int id)
        {
            return entities.Blogs.SingleOrDefault(blog => blog.ID == id);
        }

        public Blog GetBlog(int userid, string URL)
        {
            return entities.Blogs.SingleOrDefault(blog => blog.UserID == userid && blog.URL == URL);
        }

        public Blog GetBlog(int userid, int blogID)
        {
            return entities.Blogs.SingleOrDefault(blog => blog.UserID == userid && blog.ID == blogID);
        }

        public Blog GetBlog(User user, int blogID)
        {
            return entities.Blogs.SingleOrDefault(b => b.UserID == user.ID && b.ID == blogID);
        }

        public Blog GetBlog(User user, Blog blog)
        {
            return entities.Blogs.SingleOrDefault(b => b.UserID == user.ID && b.ID == blog.ID);
        }

        public IQueryable<Blog> GetAllBlogs()
        {
            return from blog in entities.Blogs
                   orderby blog.UserID
                   select blog;
        }

        public IQueryable<Blog> GetBlogsForUser(User user)
        {
            return from blog in entities.Blogs
                   where blog.UserID == user.ID
                   orderby blog.Timestamp
                   select blog;
        }

        public IQueryable<Blog> GetBlogsByCategory(int categoryID)
        {
            return from blog in entities.Blogs
                   where blog.CategoryID == categoryID
                   orderby blog.Timestamp
                   select blog;

        }

        public void AddAdvertToBlog(Blog blog, Advert advert)
        {
            blog.Adverts.Add(advert);
            Save();
        }

        #endregion

        #region Insert/Delete

        private void AddBlog(Blog blog)
        {
            if (ExistsForUser(GetUser(blog.UserID),blog))
                throw new ArgumentException(BlogAlreadyExists);

            entities.Blogs.AddObject(blog);
        }

        public void CreateBlog(string username, string blogname, string blogurl, string keywords, int categoryID)
        {
            //TODO category ID

            if (string.IsNullOrEmpty(username.Trim()))
                throw new ArgumentException("The user name provided is invalid. Please check the value and try again.");
            if (string.IsNullOrEmpty(blogname.Trim()))
                throw new ArgumentException("The blog name provided is invalid. Please check the value and try again.");
            if (string.IsNullOrEmpty(blogurl.Trim()))
                throw new ArgumentException("The blog URL provided is invalid. Please check the value and try again.");
            if (string.IsNullOrEmpty(keywords.Trim()))
                throw new ArgumentException("The keywords are invalid. Please check the values and try again.");
            if(GetBlog(blogurl) != null)
                throw new ArgumentException("A blog with this URL has already been added to our system. If this is your blog then make sure you are not adding the same blog again. If this is your blog and you think another user has added it, report this to support@platform.com");

            User user = GetUser(username);

            Blog newBlog = new Blog()
            {
                Name = blogname.Trim(),
                URL = blogurl.Trim(),
                Keywords = keywords.Trim(),
                Timestamp = DateTime.Now,
                UserID = user.ID,
                CategoryID = categoryID
            };

            try
            {
                AddBlog(newBlog);
                // Immediately persist the user data
                Save();
            }
            catch (ArgumentException ae)
            {
                throw ae;
            }
            catch (Exception)
            {
                throw new ArgumentException("The authentication provider returned an error. Please verify your entry and try again. " +
                    "If the problem persists, please contact your system administrator.");
            }
        }

        public void DeleteBog(Blog blog)
        {
            if (!BlogExists(blog))
                throw new ArgumentException("Blog does not exists");

            entities.Blogs.DeleteObject(blog);
        }

        #endregion

        #region Helper Methods

        public bool BlogExists(Blog blog)
        {
            if (blog == null)
                return false;

            return (entities.Blogs.SingleOrDefault(b => b.ID == blog.ID) != null);
        }

        public bool ExistsForUser(User user, Blog blog)
        {
            if (blog == null)
                return false;

            return (GetBlog(user, blog) != null);
        }

        public bool ExistsForUser(User user, int blogID)
        {
            return (GetBlog(user, blogID) != null);
        }

        public bool CheckAdAdvert(User user, Blog blog, Advert advert)
        {
            return user!= null && blog!= null && advert!= null && ExistsForUser(user, blog.ID) && !blog.Adverts.Contains(advert);
        }



        #endregion
    }
}